package cdu.sl.service.impl;

import cdu.sl.common.utils.BaseContext;
import cdu.sl.controller.ClassGroupController;
import cdu.sl.domain.dto.*;
import cdu.sl.domain.po.*;
import cdu.sl.domain.vo.ClassGroupVO;
import cdu.sl.exception.BusinessException;
import cdu.sl.mapper.*;
import cdu.sl.service.ClassGroupService;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 班级服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ClassGroupServiceImpl extends ServiceImpl<ClassGroupMapper, ClassGroup> implements ClassGroupService {

    private final ClassGroupMapper classGroupMapper;
    private final ClassMemberMapper classMemberMapper;
    private final UserMapper userMapper;
    private final ClassStudySetMapper classStudySetMapper;
    private final StudySetMapper studySetMapper;


    /**
     * 创建班级
     *
     * @param classGroupCreateDTO 班级创建DTO
     * @return 创建后的班级信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ClassGroupVO createClassGroup(ClassGroupCreateDTO classGroupCreateDTO) {
        // 1. 获取当前用户ID
        Long userId = BaseContext.getCurrentId();

        // 2. 检查用户是否存在
        User user = userMapper.selectById(userId);
        Assert.notNull(user, "用户不存在");

        // 3. 创建班级对象并设置属性
        ClassGroup classGroup = new ClassGroup();
        BeanUtil.copyProperties(classGroupCreateDTO, classGroup);
        classGroup.setCreatorId(userId);
        classGroup.setMemberCount(1); // 创建时只有创建者一个成员
        classGroup.setStatus(0); // 设置为活跃状态
        classGroup.setJoinCode(generateJoinCode()); // 生成随机加入码

        // 4. 保存班级信息
        classGroupMapper.insert(classGroup);

        // 5. 创建者自动成为班级成员（管理员角色）
        ClassMember classMember = new ClassMember();
        classMember.setClassId(classGroup.getId());
        classMember.setUserId(userId);
        classMember.setRole(1); // 设置为管理员角色
        classMember.setStatus(1); // 设置为已加入状态
        classMember.setJoinedAt(LocalDateTime.now());
        classMember.setLastActiveAt(LocalDateTime.now());
        classMember.setNickname(user.getUsername()); // 使用用户名作为默认昵称

        classMemberMapper.insert(classMember);

        // 6. 封装并返回班级视图对象
        ClassGroupVO classGroupVO = new ClassGroupVO();
        BeanUtil.copyProperties(classGroup, classGroupVO);
        classGroupVO.setCreatorName(user.getUsername());

        return classGroupVO;
    }

    /**
     * 根据ID获取班级详情
     *
     * @param id 班级ID
     * @return 班级详情
     */
    @Override
    public ClassGroupVO getClassGroupById(Long id) {
        // 获取班级信息
        ClassGroup classGroup = classGroupMapper.selectById(id);
        if (classGroup == null) {
            throw new BusinessException("班级不存在");
        }

        // 获取创建者信息
        User creator = userMapper.selectById(classGroup.getCreatorId());

        // 获取班级学习集信息
        List<ClassStudySet> classStudySetList = classStudySetMapper.selectByClassId(id);
        // 封装查询到的学习集结果
        List<StudySet> studySetList = classStudySetList.stream().map(classStudySet -> studySetMapper.selectById(classStudySet.getStudySetId())).collect(Collectors.toList());

        // 获取班级成员信息
        QueryWrapper<ClassMember> wrapper = new QueryWrapper<ClassMember>().eq("class_id", id);
        List<ClassMember> classMemberList = classMemberMapper.selectList(wrapper);


        // 封装班级视图对象
        ClassGroupVO classGroupVO = new ClassGroupVO();
        classGroupVO.setStudySetList(studySetList);
        BeanUtil.copyProperties(classGroup, classGroupVO);
        classGroupVO.setCreatorName(creator != null ? creator.getUsername() : "未知用户");
        classGroupVO.setClassMemberList(classMemberList);
        if (Objects.equals(BaseContext.getCurrentId(), creator.getId())) {
            classGroupVO.setIsCreator(true);
        } else {
            classGroupVO.setIsCreator(false);
        }

        return classGroupVO;
    }

    /**
     * 获取当前用户创建的所有班级
     *
     * @return 班级列表
     */
    @Override
    public List<ClassGroupVO> getCurrentUserCreatedClassGroups() {
        Long userId = BaseContext.getCurrentId();

        // 查询当前用户创建的班级
        List<ClassGroup> classGroups = lambdaQuery()
                .eq(ClassGroup::getCreatorId, userId)
                .orderByDesc(ClassGroup::getCreatedAt)
                .list();

        // 转换为VO对象
        return convertToClassGroupVOList(classGroups);
    }

    /**
     * 获取当前用户加入的所有班级
     *
     * @return 班级列表
     */
    @Override
    public List<ClassGroupVO> getCurrentUserJoinedClassGroups() {
        Long userId = BaseContext.getCurrentId();

        // 查询当前用户加入的班级成员记录
        List<ClassMember> classMembers = classMemberMapper.selectByUserId(userId);
        if (classMembers.isEmpty()) {
            return new ArrayList<>();
        }

        // 提取班级ID列表
        List<Long> classIds = classMembers.stream()
                .map(ClassMember::getClassId)
                .collect(Collectors.toList());

        // 查询班级信息
        List<ClassGroup> classGroups = lambdaQuery()
                .in(ClassGroup::getId, classIds)
                .orderByDesc(ClassGroup::getCreatedAt)
                .list();

        return classGroups.stream().map(classGroup -> {
            ClassGroupVO classGroupVO = new ClassGroupVO();
            BeanUtil.copyProperties(classGroup, classGroupVO);
            QueryWrapper<ClassMember> queryWrapper = new QueryWrapper<ClassMember>().eq("class_id", classGroup.getId()).eq("user_id", userId);
            // 设置必要字段
            User creator = userMapper.selectById(classGroup.getCreatorId());
            classGroupVO.setCreatorName(creator.getUsername());
            classGroupVO.setIsCreator(Objects.equals(userId, creator.getId()));
            // 设置当前用户在此班级中的状态
            classGroupVO.setCurrentUserStatus(classMemberMapper.selectOne(queryWrapper).getStatus());
            return classGroupVO;
        }).collect(Collectors.toList());

    }

    /**
     * 生成班级加入码
     *
     * @return 班级加入码
     */
    @Override
    public String generateJoinCode() {
        // 字符集：大写字母和数字
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder joinCode = new StringBuilder();
        Random random = new Random();

        // 生成6位随机加入码
        for (int i = 0; i < 6; i++) {
            int index = random.nextInt(characters.length());
            joinCode.append(characters.charAt(index));
        }

        // 检查该加入码是否已存在，如果存在则重新生成
        ClassGroup existingClass = lambdaQuery()
                .eq(ClassGroup::getJoinCode, joinCode.toString())
                .one();

        if (existingClass != null) {
            return generateJoinCode(); // 递归重新生成
        }

        return joinCode.toString();
    }

    /**
     * 将ClassGroup列表转换为ClassGroupVO列表
     */
    private List<ClassGroupVO> convertToClassGroupVOList(List<ClassGroup> classGroups) {
        if (classGroups == null || classGroups.isEmpty()) {
            return new ArrayList<>();
        }

        // 提取创建者ID列表
        List<Long> creatorIds = classGroups.stream()
                .map(ClassGroup::getCreatorId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询创建者信息
        List<User> creators = userMapper.selectBatchIds(creatorIds);

        // 创建用户ID到用户名的映射
        Map<Long, String> userIdToNameMap = creators.stream()
                .collect(Collectors.toMap(User::getId, User::getUsername, (k1, k2) -> k1));

        // 转换为VO对象
        return classGroups.stream().map(classGroup -> {
            ClassGroupVO vo = new ClassGroupVO();
            BeanUtil.copyProperties(classGroup, vo);
            // 是否为创建者
            vo.setIsCreator(Objects.equals(classGroup.getCreatorId(), BaseContext.getCurrentId()));
            vo.setCreatorName(userIdToNameMap.getOrDefault(classGroup.getCreatorId(), "未知用户"));
            return vo;
        }).collect(Collectors.toList());


    }


    /**
     * 修改班级信息
     *
     * @param classGroupUpdateDTO 更新班级信息数据传输对象
     */
    @Override
    @Transactional
    public void updateClass(ClassGroupUpdateDTO classGroupUpdateDTO) {
        // 1.检查班级是否存在
        ClassGroup classGroup = lambdaQuery().eq(ClassGroup::getId, classGroupUpdateDTO.getClassId()).one();
        Long userId = BaseContext.getCurrentId();
        Assert.notNull(classGroup, "班级不存在！");

        // 2.更新班级基本信息
        UpdateWrapper<ClassGroup> updateWrapper = new UpdateWrapper<ClassGroup>().eq("id", classGroupUpdateDTO.getClassId());
        classGroup.setCreatorId(userId);
        BeanUtil.copyProperties(classGroupUpdateDTO, classGroup);
        classGroupMapper.update(classGroup, updateWrapper);

        // 2.2 如果班级审核资质发生了变化 放行此刻所有没有审核通过的学生
        if(!classGroupUpdateDTO.getRequireApproval()){
            classMemberMapper.updateMemberStatusBatch(classGroupUpdateDTO.getClassId());
        }

        // 3.更新班级学习集信息
        // 先删除所有有关此班级的学习记录
        QueryWrapper<ClassStudySet> queryWrapper = new QueryWrapper<ClassStudySet>().eq("class_id", classGroupUpdateDTO.getClassId());
        classStudySetMapper.delete(queryWrapper);

        // 3.1 检查id合法性
        for (Long studySetId : classGroupUpdateDTO.getStudySetIds()) {
            StudySet studySet = studySetMapper.selectById(studySetId);
            Assert.notNull(studySet, "学习集不存在~");

            // 3.2 插入所有学习记录
            // 构造插入目标
            ClassStudySet classStudySet = new ClassStudySet();
            classStudySet.setAddedById(userId);
            BeanUtil.copyProperties(classGroupUpdateDTO, classStudySet);
            classStudySet.setStudySetId(studySetId);
            // 执行插入
            classStudySetMapper.insert(classStudySet);
        }

    }


    /**
     * 用户通过加入码加入班级
     *
     * @param userJoinClassDTO 加入码
     */
    @Override
    public void joinClass(UserJoinClassDTO userJoinClassDTO) {
        // 1. 通过joinCode搜索班级信息
        ClassGroup classGroup = lambdaQuery().eq(ClassGroup::getJoinCode, userJoinClassDTO.getJoinCode()).one();
        Assert.notNull(classGroup, "班级不存在~");

        // 2.判断是否需要审核

        // 不需要审核 直接加入
        // 2. 更新tb_class_members表信息 , 创建关联
        Long joinerId = BaseContext.getCurrentId();
        User joiner = userMapper.selectById(joinerId);

        // 构造对象并设定属性值
        ClassMember classMember = new ClassMember();
        classMember.setClassId(classGroup.getId());
        if (classGroup.getRequireApproval()) {
            // 需要审核 将成员状态设置为待审核
            log.info("加入班级需要审核 , 待审核...");
            classMember.setStatus(0);
        } else {
            // 无需审核 将成员状态设置为已加入
            log.info("加入班级无需审核 , 等待审核...");
            classMember.setStatus(1);
        }
        classMember.setUserId(joinerId);
        classMember.setNickname(joiner.getUsername());
        classMember.setRole(0);   // 通过邀请码进入 ，默认为学生
        classMember.setJoinedAt(LocalDateTime.now());
        classMemberMapper.insert(classMember);
    }


    /**
     * 删除班级信息
     *
     * @param id
     */
    @Override
    @Transactional
    public void deleteClass(Long id) {
        // 删除班级基本信息
        classGroupMapper.deleteById(id);
        // 删除班级学习集信息
        QueryWrapper<ClassStudySet> studySetQueryWrapper = new QueryWrapper<ClassStudySet>().eq("class_id", id);
        classStudySetMapper.delete(studySetQueryWrapper);
        // 删除班级成员信息
        QueryWrapper<ClassMember> classMemberQueryWrapper = new QueryWrapper<ClassMember>().eq("class_id", id);
        classMemberMapper.delete(classMemberQueryWrapper);
    }


    /**
     * 审核成员状态DTO
     *
     * @param checkClassMembersDTO 审核成员状态DTO
     */
    @Override
    public void checkMembersStatus(CheckClassMembersDTO checkClassMembersDTO) {
        // 1.检查id合法性
        ClassGroup classGroup = lambdaQuery().eq(ClassGroup::getId, checkClassMembersDTO.getClassId()).one();
        Assert.notNull(classGroup, "班级不存在");

        // 2.更新学员状态信息
        for (ClassMembersStatusUpdateDTO classMembersStatusUpdateDTO : checkClassMembersDTO.getClassMembersStatusUpdateDTOList()) {
            classMemberMapper.updateMembersStatus(checkClassMembersDTO.getClassId(), classMembersStatusUpdateDTO.getMemberId(), classMembersStatusUpdateDTO.getStatus());
        }

        // 3.更新班级人数信息
        // 只查询已加入的人数
        QueryWrapper<ClassMember> queryWrapper=new QueryWrapper<ClassMember>().eq("status",1).eq("class_id",classGroup.getId());
        Integer memberCount=classMemberMapper.selectCount(queryWrapper);
        UpdateWrapper<ClassGroup> updateWrapper=new UpdateWrapper<ClassGroup>().set("member_count",memberCount);
        classGroupMapper.update(classGroup,updateWrapper);
    }


    /**
     * 根据加入码查询班级信息
     * @param joinCode 加入码
     * @return 班级信息视图模型
     */
    @Override
    public ClassGroupVO getClassGroupByJoinCode(String joinCode) {
        ClassGroup classGroup=lambdaQuery().eq(ClassGroup::getJoinCode,joinCode).one();
        ClassGroupVO classGroupVO=new ClassGroupVO();
        BeanUtil.copyProperties(classGroup,classGroupVO);
        return classGroupVO;
    }


}